﻿//***************************************************************
// 脚本名称：Sprite
// 类创建人：周  波
// 创建日期：2016.03
// 功能描述：游戏精灵，所有游戏动态创建的精灵对象的基类
//***************************************************************
using UnityEngine;
using System.Collections;

public class GameSpriteInitializeParam
{
    /// <summary>
    /// 显示对象资源名
    /// </summary>
    public string ResourceName;
    
    /// <summary>
    /// 位置
    /// </summary>
    public Vector3 Position;

    /// <summary>
    /// 朝向
    /// </summary>
    public Vector3 Orientation;

    /// <summary>
    /// 资源加载完成后回调
    /// </summary>
    public System.Action<bool> LoadResourceComplateCallBack = null;
}

public abstract class GameSprite : MonoBehaviour
{
    /// <summary>
    /// 实体对象
    /// </summary>
    public GameObject MyGameObject { get; protected set; }
    /// <summary>
    /// 实体对象空间属性
    /// </summary>
    public Transform MyTransform { get; protected set; }

    /// <summary>
    /// 模型资源名称
    /// </summary>
    public string ResourceName { get; private set; }

    private System.Action<bool> m_LoadResourceComplateCallBack = null;
    /// <summary>
    /// 初始化
    /// </summary>
    /// <param name="param">初始化参数</param>
    /// <returns>true：成功；false：失败</returns>
    public bool InitializeSprite(GameSpriteInitializeParam param)
    {
        MyGameObject = gameObject;
        MyTransform = transform;
        SetPosition(param.Position);
        SetOrientation(param.Orientation.x, param.Orientation.z);
        SetTag();
        SetLayer();
        m_LoadResourceComplateCallBack = param.LoadResourceComplateCallBack;
        this.ResourceName = param.ResourceName;
        // 请求显示对象资源
        StartCoroutine("LoadResource", param.ResourceName);
        return true;
    }

    /// <summary>
    /// 设置Tag，Init时候
    /// </summary>
    protected virtual void SetTag()
    {

    }

    /// <summary>
    /// 设置Layer，Init时候 和 在加载完成模型后调用
    /// </summary>
    protected virtual void SetLayer()
    {
    }

    /// <summary>
    /// 销毁
    /// </summary>
    public void UninitializeSprite()
    {
        StopCoroutine("LoadResource");
    }

    /// <summary>
    /// 加载实体资源
    /// </summary>
    /// <param name="resourceName">资源名</param>
    private IEnumerator LoadResource(string resourceName)
    {
        AssetBundleLoadAssetOperation resourceOperation = AssetBundleManager.Instance().LoadAssetAsync(resourceName, typeof(GameObject));
        if (resourceOperation == null)
        {
            NotifyLoadResourceCompalted(false);
            yield break;
        }
        yield return StartCoroutine(resourceOperation);

        GameObject obj = GameObject.Instantiate(resourceOperation.GetAsset<Object>()) as GameObject;
        if (obj == null)
        {
            Debug.LogError(string.Format("Failed to load resource[{0}]!", resourceName));
            NotifyLoadResourceCompalted(false);
            yield break;
        }
        obj.transform.parent = MyTransform;
        obj.transform.localPosition = Vector3.zero;
        obj.transform.localRotation = Quaternion.identity;
        LoadModelComplated(obj);
        SetTag();
        SetLayer();
        NotifyLoadResourceCompalted(true);
    }

    void NotifyLoadResourceCompalted(bool isComplated)
    {
        if (m_LoadResourceComplateCallBack != null)
        {
            m_LoadResourceComplateCallBack(isComplated);
        }
    }

    /// <summary>
    /// 加载模型完成:在模型加载完成并且已经添加到对应的节点后调用此方法
    /// </summary>
    protected virtual void LoadModelComplated(GameObject model)
    {
    }

    /// <summary>
    /// 设置坐标
    /// </summary>
    /// <param name="position"></param>
    void InternalSetPosition(Vector3 position)
    {
        MyTransform.position = position;
    }

    /// <summary>
    /// 设置坐标
    /// </summary>
    /// <param name="position"></param>
    public virtual void SetPosition(Vector3 position)
    {
        InternalSetPosition(position);
    }

    /// <summary>
    /// 设置坐标
    /// </summary>
    /// <param name="x"></param>
    /// <param name="y"></param>
    /// <param name="z"></param>
    public virtual void SetPosition(float x, float y, float z)
    {
        InternalSetPosition(new Vector3(x, y, z));
    }

    /// <summary>
    /// 当前坐标
    /// </summary>
    public Vector3 CurrentPosition
    {
        get
        {
            return MyTransform.position;
        }
    }

    /// <summary>
    /// 设置实体朝向为指定向量（Y轴向上）
    /// </summary>
    /// <param name="x">向量X分量</param>
    /// <param name="z">向量Y分量</param>
    public void SetOrientation(float x, float z)
    {
        Vector3 forward = Vector3.zero;
        forward.x = x;
        forward.y = 0;
        forward.z = z;
        forward.Normalize();
        // 容错，朝向不允许出现向量为0的情况
        if (forward == Vector3.zero)
        {
            forward = -Vector3.forward;
        }
        MyTransform.forward = forward;
    }

    /// <summary>
    /// 设置实体朝向某个坐标点(实际生效的是x,z 方向)
    /// </summary>
    /// <param name="point"></param>
    public void SetOrientationPoint(Vector3 point)
    {
        Vector3 orientation = point - CurrentPosition;
        SetOrientation(orientation.x, orientation.z);
    }

    /// <summary>
    /// 获取实体朝向
    /// </summary>
    /// <returns></returns>
    public Vector3 GetOrientation()
    {
        return MyTransform.forward;
    }
}

